# -*- coding: utf-8 -*-
# Author   : ZhangQing
# Time     : 2025-08-12 12:30
# File     : conftest.py
# Project  : codebuddy_craft
# Desc     : 测试配置

"""
测试配置 🧪

提供测试环境配置和通用测试工具
"""

import os
import asyncio
import pytest
import logging
from typing import Dict, Any, Generator, AsyncGenerator

from fastapi import FastAPI
from fastapi.testclient import TestClient
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool

from backend.core.app_config import create_app
from backend.core.settings import Settings, get_settings
from backend.database.connection import get_db, Base
from backend.utils.logger import setup_logging

# 设置测试环境变量
os.environ["ENVIRONMENT"] = "testing"
os.environ["DATABASE_URL"] = "sqlite+aiosqlite:///:memory:"
os.environ["DEBUG"] = "true"


# 测试设置覆盖
def get_test_settings() -> Settings:
    """获取测试配置 ⚙️"""
    return Settings(
        ENVIRONMENT="testing",
        DATABASE_URL="sqlite+aiosqlite:///:memory:",
        DEBUG=True,
        SECRET_KEY="test_secret_key",
        LOG_LEVEL="ERROR",
        PERFORMANCE_MONITORING=False,
        AUDIT_ENABLED=False
    )


# 覆盖设置
@pytest.fixture(scope="session")
def settings() -> Settings:
    """测试配置夹具 ⚙️"""
    return get_test_settings()


# 创建测试数据库引擎
@pytest.fixture(scope="session")
def engine():
    """测试数据库引擎夹具 🔧"""
    # 使用内存数据库
    test_engine = create_async_engine(
        "sqlite+aiosqlite:///:memory:",
        poolclass=NullPool,
        connect_args={"check_same_thread": False}
    )
    
    return test_engine


# 创建测试数据库会话
@pytest.fixture(scope="function")
async def db_session(engine) -> AsyncGenerator[AsyncSession, None]:
    """测试数据库会话夹具 📋"""
    # 创建所有表
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)
    
    # 创建会话
    async_session = sessionmaker(
        engine, class_=AsyncSession, expire_on_commit=False
    )
    
    async with async_session() as session:
        yield session
        await session.rollback()
    
    # 清理表
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.drop_all)


# 创建测试应用
@pytest.fixture(scope="function")
def app(db_session) -> FastAPI:
    """测试应用夹具 🚀"""
    # 设置日志级别为ERROR，减少测试输出
    setup_logging(log_level=logging.ERROR)
    
    # 创建应用
    test_app = create_app()
    
    # 覆盖数据库依赖
    async def override_get_db():
        yield db_session
    
    test_app.dependency_overrides[get_db] = override_get_db
    
    return test_app


# 创建测试客户端
@pytest.fixture(scope="function")
def client(app) -> Generator[TestClient, None, None]:
    """测试客户端夹具 🌐"""
    with TestClient(app) as test_client:
        yield test_client


# 创建测试用户
@pytest.fixture(scope="function")
async def test_user(db_session) -> Dict[str, Any]:
    """测试用户夹具 👤"""
    from backend.models.user import User
    from backend.utils.security import get_password_hash
    
    # 创建测试用户
    test_user = User(
        username="testuser",
        email="test@example.com",
        full_name="Test User",
        hashed_password=get_password_hash("testpassword"),
        is_active=True,
        is_verified=True
    )
    
    db_session.add(test_user)
    await db_session.commit()
    await db_session.refresh(test_user)
    
    return {
        "id": str(test_user.id),
        "username": test_user.username,
        "email": test_user.email,
        "password": "testpassword"
    }


# 创建测试管理员
@pytest.fixture(scope="function")
async def test_admin(db_session) -> Dict[str, Any]:
    """测试管理员夹具 👑"""
    from backend.models.user import User
    from backend.utils.security import get_password_hash
    
    # 创建测试管理员
    test_admin = User(
        username="admin",
        email="admin@example.com",
        full_name="Admin User",
        hashed_password=get_password_hash("adminpassword"),
        is_active=True,
        is_verified=True,
        is_superuser=True
    )
    
    db_session.add(test_admin)
    await db_session.commit()
    await db_session.refresh(test_admin)
    
    return {
        "id": str(test_admin.id),
        "username": test_admin.username,
        "email": test_admin.email,
        "password": "adminpassword"
    }


# 创建认证头
@pytest.fixture(scope="function")
async def auth_headers(client, test_user) -> Dict[str, str]:
    """认证头夹具 🔑"""
    # 登录获取令牌
    response = client.post(
        "/api/v1/auth/login",
        data={
            "username": test_user["username"],
            "password": test_user["password"]
        }
    )
    
    tokens = response.json()
    
    return {"Authorization": f"Bearer {tokens['access_token']}"}


# 创建管理员认证头
@pytest.fixture(scope="function")
async def admin_headers(client, test_admin) -> Dict[str, str]:
    """管理员认证头夹具 👑"""
    # 登录获取令牌
    response = client.post(
        "/api/v1/auth/login",
        data={
            "username": test_admin["username"],
            "password": test_admin["password"]
        }
    )
    
    tokens = response.json()
    
    return {"Authorization": f"Bearer {tokens['access_token']}"}


# 创建测试项目
@pytest.fixture(scope="function")
async def test_project(db_session, test_user) -> Dict[str, Any]:
    """测试项目夹具 📁"""
    from backend.models.project import Project
    
    # 创建测试项目
    test_project = Project(
        name="Test Project",
        description="A test project",
        owner_id=test_user["id"],
        settings={
            "language": "python",
            "visibility": "private"
        }
    )
    
    db_session.add(test_project)
    await db_session.commit()
    await db_session.refresh(test_project)
    
    return {
        "id": str(test_project.id),
        "name": test_project.name,
        "description": test_project.description,
        "owner_id": test_user["id"]
    }


# 创建测试文件
@pytest.fixture(scope="function")
async def test_file(db_session, test_project) -> Dict[str, Any]:
    """测试文件夹具 📄"""
    from backend.models.file import File
    
    # 创建测试文件
    test_file = File(
        name="test_file.py",
        path="/test_file.py",
        content="print('Hello, World!')",
        project_id=test_project["id"],
        size=22,
        lines=1,
        mime_type="text/x-python"
    )
    
    db_session.add(test_file)
    await db_session.commit()
    await db_session.refresh(test_file)
    
    return {
        "id": str(test_file.id),
        "name": test_file.name,
        "path": test_file.path,
        "content": test_file.content,
        "project_id": test_project["id"]
    }


# 跳过慢测试的标记
skip_slow = pytest.mark.skipif(
    os.environ.get("SKIP_SLOW_TESTS") == "1",
    reason="Skipping slow tests"
)

# 只在CI环境运行的标记
ci_only = pytest.mark.skipif(
    os.environ.get("CI") != "1",
    reason="Test only runs in CI environment"
)

# 需要外部服务的标记
requires_external = pytest.mark.skipif(
    os.environ.get("EXTERNAL_SERVICES") != "1",
    reason="Test requires external services"
)